package com.tcm.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tcm.entity.Role;
import com.tcm.entity.RoleUser;
import com.tcm.entity.Teacher;
import com.tcm.entity.User;
import com.tcm.entity.dto.param.RoleTeacherUpdateParam;
import com.tcm.entity.resp.PageR;
import com.tcm.entity.vo.RoleSelectResult;
import com.tcm.entity.vo.RoleTeacherListResult;
import com.tcm.exception.DatabaseOperationException;
import com.tcm.mapper.RoleMapper;
import com.tcm.mapper.RoleUserMapper;
import com.tcm.service.RoleService;
import com.tcm.service.TeacherService;
import com.tcm.service.UserService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * @author Guqier
 * @version 1.0
 * @date 2023/7/2 22:22
 */
@Service
public class RoleServiceImpl extends ServiceImpl<RoleMapper, Role> implements RoleService {

    @Autowired
    private RoleUserMapper roleUserMapper;

    @Autowired
    private TeacherService teacherService;

    @Autowired
    private UserService userService;

    private static final int NORMAL_ROLE_TYPE = 0;

    private static final int DIY_ROLE_TYPE = 2;

    public static final String ADMIN_ROLE_KEY = "admin";// 管理员角色码

    public static final String TEACHER_ROLE_KEY = "teacher";// 教师角色码

    /**
     * 通过用户ID获取用户所有角色码
     * @param userId 用户ID
     * @return 所有角色码
     */
    @Override
    public List<String> getUserRoleKey(Long userId){
        LambdaQueryWrapper<RoleUser> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(RoleUser::getUserId, userId);
        List<RoleUser> roleUsers = roleUserMapper.selectList(queryWrapper);

        List<String> res = new ArrayList<>();
        for (RoleUser roleUser : roleUsers) {
            Role role = this.getById(roleUser.getRoleId());
            res.add(role.getRoleKey());
        }
        return res;
    }

    /**
     * 获取角色列表
     * @return 角色列表
     */
    @Override
    public List<RoleSelectResult> getRoleList(){
        LambdaQueryWrapper<Role> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Role::getType, NORMAL_ROLE_TYPE).or().eq(Role::getType, DIY_ROLE_TYPE);
        List<Role> list = this.list(queryWrapper);
        List<RoleSelectResult> results = new ArrayList<>();
        for (Role role : list) {
            RoleSelectResult roleSelectResult = new RoleSelectResult();
            BeanUtils.copyProperties(role, roleSelectResult);
            results.add(roleSelectResult);
        }
        return results;
    }

    /**
     * 分页获取教师角色列表
     * @param page 当前页码
     * @param pageSize 页面大小
     * @param name 查询姓名
     * @param account 查询账号
     * @return 分页教师角色列表
     */
    @Override
    public PageR<RoleTeacherListResult> getTeacherRoleListByPage(Integer page, Integer pageSize, String name, String account){
        // 分页获取教师列表
        Page<Teacher> teacherPage = new Page<>(page, pageSize);
        teacherPage.addOrder(OrderItem.desc("update_time"));
        LambdaQueryWrapper<Teacher> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(name != null, Teacher::getName, name)
                .like(account != null , Teacher::getAccount, account);
        teacherService.page(teacherPage, queryWrapper);
        // 处理结果，封装结果集
        List<RoleTeacherListResult> resRecords = new ArrayList<>();
        List<Teacher> records = teacherPage.getRecords();
        PageR<RoleTeacherListResult> pageR = new PageR<>();
        BeanUtils.copyProperties(teacherPage, pageR, "records");
        // 获取所有角色用户关系
        List<RoleUser> roleUsers = roleUserMapper.selectList(null);
        // 获取所有角色列表
        List<RoleSelectResult> roles = this.getRoleList();
        for (Teacher teacher : records) {
            RoleTeacherListResult vo = new RoleTeacherListResult();
            BeanUtils.copyProperties(teacher, vo);
            User user = userService.getUserByAccount(vo.getAccount());
            // 查找当前教师角色
            List<RoleSelectResult> nowRoles = new ArrayList<>();
            for (RoleUser roleUser : roleUsers) {
                if (roleUser.getUserId().equals(user.getId())){
                    Optional<RoleSelectResult> first = roles.stream().filter(r -> r.getId().equals(roleUser.getRoleId())).findFirst();
                    first.ifPresent(nowRoles::add);
                }
            }
            vo.setRoles(nowRoles);
            resRecords.add(vo);
        }
        pageR.setRecords(resRecords);
        return pageR;
    }

    /**
     * 更新教师用户角色
     * @param param 参数封装
     * @param currUserId 当前用户ID
     * @return 处理结果，true为成功
     * @throws DatabaseOperationException 数据库操作异常
     */
    @Override
    @Transactional
    public boolean modifyTeacherRole(RoleTeacherUpdateParam param, Long currUserId) throws DatabaseOperationException{
        // 查询教师是否存在
        Teacher teacher = teacherService.getById(param.getTeacherId());
        if (teacher == null) {
            return false;
        }
        User user = userService.getUserByAccount(teacher.getAccount());
        // 删除已有角色关系
        LambdaQueryWrapper<RoleUser> roleUserLambdaQueryWrapper = new LambdaQueryWrapper<>();
        roleUserLambdaQueryWrapper.eq(RoleUser::getUserId, user.getId());
        Integer roleUserCount = roleUserMapper.selectCount(roleUserLambdaQueryWrapper);
        int delete = roleUserMapper.delete(roleUserLambdaQueryWrapper);
        // 更新角色关系
        int cnt = 0;
        for (Long roleId : param.getRoleIds()) {
            // 查询角色是否存在
            Role role = this.getById(roleId);
            if (role == null){
                continue;
            }
            // 如果不存在则插入角色关系
            RoleUser roleUser = new RoleUser();
            roleUser.setUserId(user.getId());
            roleUser.setRoleId(roleId);
            roleUser.setCreateUser(currUserId);
            roleUser.setUpdateUser(currUserId);
            cnt += roleUserMapper.insert(roleUser);
        }
        if (cnt != param.getRoleIds().size() || roleUserCount != delete) {
            throw new DatabaseOperationException("数据库操作失败");
        }
        return true;
    }

    /**
     * 判断用户是否是管理员
     * @param userId 用户ID
     * @return true为是
     */
    @Override
    public boolean isAdministrator(Long userId){
        return isWho(userId, ADMIN_ROLE_KEY);
    }

    /**
     * 判断用户是否是教师
     * @param userId 用户ID
     * @return true为是
     */
    @Override
    public boolean isTeacher(Long userId){
        return isWho(userId, TEACHER_ROLE_KEY);
    }

    public boolean isWho(Long userId, String roleKey){
        LambdaQueryWrapper<RoleUser> roleUserLambdaQueryWrapper = new LambdaQueryWrapper<>();
        roleUserLambdaQueryWrapper.eq(RoleUser::getUserId, userId);
        // 获取当前用户所有角色
        List<RoleUser> roleUsers = roleUserMapper.selectList(roleUserLambdaQueryWrapper);
        List<Role> roles = this.listByIds(roleUsers.stream().map(RoleUser::getRoleId).collect(Collectors.toList()));
        // 判断是否是管理员
        Optional<Role> first = roles.stream().filter(role -> role.getRoleKey().equals(roleKey)).findFirst();
        return first.isPresent();
    }

}
